﻿using BlueWind.Mediator.ServiceContracts;
using BlueWind.Mediator.ServiceContracts.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.ServiceModel;

namespace BlueWind.Mediator.Server
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Mediator : IMediator, IPrototype<Mediator>
    {
        public MediatorType Type;
        private HandSakeBase handSake;
        private Dictionary<String, IColleague> memberDictionary;

        public Mediator()
        {
            memberDictionary = new Dictionary<string, IColleague>();
        }

        private event Callback Respond;

        public Boolean CanBeDestroy
        {
            get
            {
                return memberDictionary.Count == 0;
            }
        }

        public HandSakeBase HandSake
        {
            get
            {
                return handSake;
            }
            set
            {
                handSake = value;
            }
        }

        public Dictionary<String, IColleague> MemberDictionary
        {
            get
            {
                return memberDictionary;
            }
            set
            {
                memberDictionary = value;
            }
        }

        public Mediator Clone()
        {
            return (Mediator)this.MemberwiseClone();
        }

        public Mediator DeepCopy()
        {
            MemoryStream stream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            Mediator copy = (Mediator)formatter.Deserialize(stream);
            stream.Close();
            return copy;
        }

        public void Register(String userName, IColleague colleague)
        {
            if (!MemberDictionary.ContainsValue(colleague))
            {
                if (!memberDictionary.ContainsKey(userName))
                {
                    MemberDictionary.Add(userName, colleague);
                    Respond += colleague.Receive;
                    ((ICommunicationObject)colleague).Faulted += HandleFaultStateOject;
                }
                else { MemberDictionary[userName] = colleague; Respond += colleague.Receive; ((ICommunicationObject)colleague).Faulted += HandleFaultStateOject; }
            }
        }

        private void HandleFaultStateOject(object sender, EventArgs e)
        {
            Respond -= ((IColleague)sender).Receive;
        }

        public void Send(String from, String room, BwMessage message, MessageType messageType)
        {
            if (Respond != null)
            {
                Respond(from, room, message, messageType);
            }
        }

        public void UnRegister(IColleague colleague, String userName)
        {
            memberDictionary.Remove(userName);
            Respond -= colleague.Receive;
        }
    }
}